package maze

import (
	"errors"
	"fmt"
	"reflect"
)

type stack struct {
	data []interface{}
	kind reflect.Kind
}

func New() stack {
	return stack{}
}
func (s *stack) Push(v interface{}) error {
	vkind := reflect.ValueOf(v).Kind()
	if len(s.data) == 0 || s.kind == reflect.Invalid {
		s.kind = vkind
	}
	if s.kind != vkind {
		return errors.New("栈只能存放同类型数据")
	}
	s.data = append(s.data, v)
	return nil
}
func (s *stack) Pop() (rtn interface{}) {
	lastIdx := len(s.data) - 1
	rtn = s.data[lastIdx]
	s.data = s.data[:lastIdx]
	return rtn
}
func (s *stack) GetTop() (rtn interface{}) {
	lastIdx := len(s.data) - 1
	rtn = s.data[lastIdx]
	return rtn
}
func (s *stack) IsEmpty() bool {
	return len(s.data) == 0
}
func (s *stack) Len() int {
	return len(s.data)
}
func (s stack) Data() []interface{} {
	return s.data
}

//延着一条路搜索,找错就回头,一直到找到
func MazeStack(start, end Point) bool {
	ms := New()
	if err := ms.Push(start); err != nil {
		fmt.Println(err)
		return false
	}
	for !ms.IsEmpty() {
		curr := ms.GetTop().(Point)
		mazeMap[curr.X][curr.Y] = 2
		findOne := false
		if curr.X == end.X && curr.Y == end.Y {
			fmt.Println(ms.Data())
			return true
		}
		for _, dir := range Dirs {
			next := dir(curr)
			if next.X >= 0 && next.Y >= 0 &&
				next.X < len(mazeMap) &&
				next.Y < len(mazeMap[next.X]) &&
				mazeMap[next.X][next.Y] == 0 {
				if err := ms.Push(next); err != nil {
					fmt.Println(err)
					return false
				}
				findOne = true
				break
			}
		}
		if !findOne {
			ms.Pop()
		}

	}
	return false
}
